import * as qiniu from 'qiniu-js';
import { ref } from 'vue';
import { RequestOption } from '@arco-design/web-vue';
import * as Lodash from 'lodash';

export type TokenResult = {
  resourceId: number;
  resourceType: number;
  domain: string;
  uploadKey: string;
  uploadToken: string;
};

export type UploadResult = {
  resId: number;
  resType?: number;
  key?: string;
  count?: number;
  item?: any;
};

export type IUploader = {
  apiFun: (data: any) => Promise<TokenResult>;
  onOk?: (result: UploadResult) => void;
  props?: {
    listType?: 'text' | 'picture' | 'picture-card';
    customRequest?: (options: any) => void;
    defaultFileList?: any[];
    limit?: number;
    onBeforeUpload?: (file: any) => boolean;
    fileList?: any[];
  };
};

export type UpFile = {
  filePath: string;
  fileName?: string;
};

export type UpResult = {
  resourceId: number;
  url: string;
  key: string;
};

export function useUploader(params: IUploader) {
  const { apiFun, onOk } = params;
  const props = params.props || {};
  if (!props.listType) {
    props.listType = 'text';
  }
  if (props.limit === undefined || props.limit === null) {
    props.limit = 0;
  }

  const uploading = ref(false);
  const progress = ref(0);
  const count = ref(0);
  const results = ref<UploadResult[]>([]);

  if (!props.onBeforeUpload) {
    props.onBeforeUpload = () => {
      count.value += 1;
      return true;
    };
  }

  const uploadTo7Niu = async (
    tokenRes: TokenResult,
    options: RequestOption
  ) => {
    const { onProgress, onError, onSuccess, fileItem, name } = options;
    uploading.value = true;
    progress.value = 0;
    const observer = qiniu.upload(
      fileItem.file as File,
      tokenRes.uploadKey,
      tokenRes.uploadToken
    );
    observer.subscribe({
      next: (res) => {
        // console.log('next:', res);
        if (res.total) {
          const total = res.total as any;
          progress.value = total.percent;
          onProgress(total.percent);
        }
      },
      error: (err) => {
        uploading.value = false;
        if (onError) onError(err);
      },
      complete: (res) => {
        uploading.value = false;
        // result.value.resId = tokenRes.resourceId;
        // result.value.key = res.key || tokenRes.uploadKey;
        // result.value.resType = tokenRes.resourceType;
        const result: UploadResult = {
          resId: tokenRes.resourceId,
          resType: tokenRes.resourceType,
          key: res.key || tokenRes.uploadKey,
        };
        if (onSuccess) {
          onSuccess(result);
        }
        if (onOk) {
          result.item = fileItem;
          onOk(result);
        }
      },
    });
  };

  const handleUpload = (options: RequestOption, uniqueParams: any = {}) => {
    const { onError, fileItem, name } = options;
    if (!fileItem || !fileItem.name) return;
    console.log('handleUpload:', name, fileItem);
    uploading.value = true;
    apiFun({ ...uniqueParams, localFileName: fileItem.name })
      .then((res) => {
        uploadTo7Niu(res, options);
      })
      .catch((err) => {
        uploading.value = false;
        if (onError) onError(err);
      });
  };

  props.customRequest = handleUpload;

  const handleChange = (data: any) => {
    // console.log('handleChange:', data.value);
    const outputs: UploadResult[] = [];
    for (let i = 0; i < data.length; i += 1) {
      const item = data[i];
      // console.log(item.status)
      if (item.status === 'done') {
        outputs.push(item.response);
      }
    }
    results.value = outputs;
    count.value = outputs.length;
  };

  const handleBeforeRemove = (file: any) => {
    console.log(file);
    if (props.defaultFileList) {
      Lodash.remove(props.defaultFileList, (item) => item.uid === file.uid);
    }
    return true;
  };

  const getResourceIds = () => {
    const ids: number[] = [];
    for (let i = 0; i < results.value.length; i += 1) {
      const item = results.value[i];
      if (item) {
        ids.push(item.resId);
      }
    }
    if (props.defaultFileList) {
      for (let i = 0; i < props.defaultFileList.length; i += 1) {
        const item = props.defaultFileList[i];
        if (item) {
          ids.push(item.uid);
        }
      }
    }
    return ids;
  };

  return {
    handleUpload,
    handleChange,
    getResourceIds,
    handleBeforeRemove,
    uploading,
    progress,
    results,
    props,
    count,
  } as const;
}
